package com.aplink.generic.xmlpullparser;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.text.TextUtils;
import android.util.Xml;

import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.pojo.TableRelationship;
import com.aplink.generic.xmlparser.XmlPaserUtil;

public class ContentDataXmlPullParser {
	private static final String DATA_RULES = "data_rules";
	private static final String DISP_PROP = "disp_prop";
	private static final String DISP_PROP_WEB_SERVICE_FUNCTION = "WebserviceFunction";
	private static final String IGNORE_REFRESH = "isIgnoreRefresh";
	private static final String IS_DEVICE_ID = "isDeviceID";
	private static final String IS_IMAGE_LOCAL_PATH = "isImageLocalPath";
	private static final String IS_LATTITUDE = "isLatitude";
	private static final String IS_LONGITUDE = "isLongitude";
	private static final String IS_MOBILE_OS = "isMobileOS";
	private static final String IS_PASSWORD = "isPassword";
	private static final String IS_TOKEN = "isToken";
	private static final String IS_USERNAME = "isUsername";
	private static final String JOIN_TYPE = "join";
	private static String mNameSpace = null;
	private static final String OBJ_CLASS_ID = "om_id";
	private static final String OBJ_PROP = "prop";
	private static final String OBJ_PROP_DATATYPE = "data_type";
	private static final String OBJ_PROP_EXPRESS = "expression";
	private static final String OBJ_PROP_F_OM_ID = "f_om_id";
	private static final String OBJ_PROP_FKEYID = "fkey_id";
	private static final String OBJ_PROP_ID = "op_id";
	private static final String OBJ_PROP_IS_CREATED_TIME = "isCreatedTime";
	private static final String OBJ_PROP_IS_GROUP_BY = "isGroupBy";
	private static final String OBJ_PROP_IS_IMAGE_SERVER_PATH = "isImageServerPath";
	private static final String OBJ_PROP_IS_SORTED_ASC = "isSortedASC";
	private static final String OBJ_PROP_IS_SORTED_DESC = "isSortedDESC";
	private static final String OBJ_PROP_IS_SYNC_STATUS = "isSyncStatus";
	private static final String OBJ_PROP_ISAUTO = "isAuto";
	private static final String OBJ_PROP_ISFKEY = "isfkey";
	private static final String OBJ_PROP_ISKEY = "iskey";
	private static final String OBJ_PROP_P_OM_ID = "p_om_id";
	private static final String OBJ_PROP_TAGNAME = "obj_prop";
	private static final String RELATIONSHIP = "relationship";
	private static final String RULE = "rule";
	private static final String SAVE = "save";

	private static final String WEB_SERVICE_VARIABLE = "WebserviceVariable";

	public static ContentData parse(int xmlFile, Context context) {
		InputStream inputStream = XmlPaserUtil.getXMLInputStream(xmlFile,
		        context);
		try {
			XmlPullParser parser = Xml.newPullParser();
			parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
			parser.setInput(inputStream, null);
			parser.nextTag();
			return read(parser);
		} catch (XmlPullParserException | IOException e) {
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return new ContentData();
	}

	private static ContentData read(XmlPullParser pullParser)
	        throws XmlPullParserException, IOException {
		pullParser.require(XmlPullParser.START_TAG, mNameSpace, DISP_PROP);
		ContentData contentData = new ContentData();
		String attributeValue = XmlPaserUtil.readAttribute(pullParser,
		        mNameSpace, DISP_PROP_WEB_SERVICE_FUNCTION);
		if (!TextUtils.isEmpty(attributeValue)) {
			contentData.setWebserviceFunction(attributeValue);
		}
		while (pullParser.next() != XmlPullParser.END_TAG) {
			if (pullParser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (pullParser.getName().equalsIgnoreCase(OBJ_PROP)) {
				String p_om_id = XmlPaserUtil.readAttribute(pullParser,
				        mNameSpace, OBJ_PROP_P_OM_ID);
				boolean isIgnoreRefresh = false;
				if (!TextUtils.isEmpty(XmlPaserUtil.readAttribute(pullParser,
				        mNameSpace, IGNORE_REFRESH))) {
					isIgnoreRefresh = XmlPaserUtil.readAttribute(pullParser,
					        mNameSpace, IGNORE_REFRESH).equalsIgnoreCase("Y");
				}
				readProp(pullParser, p_om_id, isIgnoreRefresh, contentData);
			}
		}
		return contentData;
	}

	private static ArrayList<String> readObjDataRules(XmlPullParser parser)
	        throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, DATA_RULES);
		ArrayList<String> dataRules = new ArrayList<>();
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (parser.getName().equalsIgnoreCase(RULE)) {
				dataRules.add(XmlPaserUtil.readText(parser));
			}
		}
		return dataRules;
	}

	private static ObjPropInfo readObjPropInfo(XmlPullParser parser)
	        throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, OBJ_PROP_TAGNAME);
		ObjPropInfo objPropInfo = new ObjPropInfo();
		if (XmlPaserUtil.readAttribute(parser, mNameSpace, SAVE) != null) {
			objPropInfo.setSave(XmlPaserUtil.isAttributeEqualYes(parser,
			        mNameSpace, SAVE));
		}
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}

			if (parser.getName().equalsIgnoreCase(OBJ_CLASS_ID)) {
				objPropInfo.setTableName(XmlPaserUtil.readText(parser));
			} else if (parser.getName().equalsIgnoreCase(OBJ_PROP_ID)) {

				objPropInfo.setLongitude(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_LONGITUDE));

				objPropInfo.setLatitude(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_LATTITUDE));

				objPropInfo.setDeviceID(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_DEVICE_ID));

				objPropInfo.setImageLocalPath(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_IMAGE_LOCAL_PATH));

				objPropInfo.setSortAsc(XmlPaserUtil.isAttributeEqualYes(parser,
				        mNameSpace, OBJ_PROP_IS_SORTED_ASC));

				objPropInfo.setSortDesc(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, OBJ_PROP_IS_SORTED_DESC));

				objPropInfo.setGroupBy(XmlPaserUtil.isAttributeEqualYes(parser,
				        mNameSpace, OBJ_PROP_IS_GROUP_BY));

				objPropInfo.setCreatedTime(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, OBJ_PROP_IS_CREATED_TIME));

				objPropInfo.setSyncStatus(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, OBJ_PROP_IS_SYNC_STATUS));

				objPropInfo.setImageServerPath(XmlPaserUtil
				        .isAttributeEqualYes(parser, mNameSpace,
				                OBJ_PROP_IS_IMAGE_SERVER_PATH));

				objPropInfo.setImageLocalPath(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_IMAGE_LOCAL_PATH));

				objPropInfo.setToken(XmlPaserUtil.isAttributeEqualYes(parser,
				        mNameSpace, IS_TOKEN));

				objPropInfo.setMobileOS(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_MOBILE_OS));

				objPropInfo.setUsername(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_USERNAME));

				objPropInfo.setDeviceID(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_DEVICE_ID));

				objPropInfo.setPassword(XmlPaserUtil.isAttributeEqualYes(
				        parser, mNameSpace, IS_PASSWORD));

				objPropInfo.setJoinType(XmlPaserUtil.readAttribute(parser,
				        mNameSpace, JOIN_TYPE));

				objPropInfo.setFKey(XmlPaserUtil.isAttributeEqualYes(parser,
				        mNameSpace, OBJ_PROP_ISFKEY));

				objPropInfo.setAuto(XmlPaserUtil.isAttributeEqualYes(parser,
				        mNameSpace, OBJ_PROP_ISAUTO));

				objPropInfo.setKey(XmlPaserUtil.isAttributeEqualYes(parser,
				        mNameSpace, OBJ_PROP_ISKEY));

				objPropInfo.setForeignObjectMapping(XmlPaserUtil.readAttribute(
				        parser, mNameSpace, OBJ_PROP_F_OM_ID));

				objPropInfo.setRelationship(TableRelationship.get(XmlPaserUtil
				        .readAttribute(parser, mNameSpace, RELATIONSHIP)));

				objPropInfo.setForiegnKey(XmlPaserUtil.readAttribute(parser,
				        mNameSpace, OBJ_PROP_FKEYID));

				objPropInfo.setDataType(XmlPaserUtil.readAttribute(parser,
				        mNameSpace, OBJ_PROP_DATATYPE));
				objPropInfo.setColumnName(XmlPaserUtil.readText(parser));
			} else if (parser.getName().equalsIgnoreCase(OBJ_PROP_EXPRESS)) {
				objPropInfo.setExpress(XmlPaserUtil.readText(parser));
			} else if (parser.getName().equalsIgnoreCase(DATA_RULES)) {
				objPropInfo.setDataRules(readObjDataRules(parser));
			}
		}
		return objPropInfo;
	}

	private static void readProp(XmlPullParser parser, String p_om_id,
	        boolean isIgnoreRefresh, ContentData contentData)
	        throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, mNameSpace, OBJ_PROP);
		while (parser.next() != XmlPullParser.END_TAG) {
			if (parser.getEventType() != XmlPullParser.START_TAG) {
				continue;
			}
			if (parser.getName().equalsIgnoreCase(OBJ_PROP_TAGNAME)) {
				String WwebserviceVariable = XmlPaserUtil.readAttribute(parser,
				        mNameSpace, WEB_SERVICE_VARIABLE);
				ObjPropInfo objPropInfo = readObjPropInfo(parser);
				objPropInfo.setTableRoot(p_om_id);
				if (objPropInfo.isImageLocalPath()) {
					contentData.setImageLocalPath(objPropInfo);
				} else if (objPropInfo.isImageServerPath()) {
					contentData.setImageServerPath(objPropInfo);
				} else if (objPropInfo.isCreatedTime()) {
					contentData.addCreatedTimeObject(objPropInfo);
				} else if (objPropInfo.isSyncStatus()) {
					contentData.addSyncStatus(objPropInfo);
				} else if (objPropInfo.isLatitude()) {
					contentData.setLongitudeCol(objPropInfo);
				} else if (objPropInfo.isLatitude()) {
					contentData.setLatitudeCol(objPropInfo);
				}

				if (objPropInfo.isSortAsc()) {
					contentData.addASCColumn(objPropInfo.getFullColumnName());
				} else if (objPropInfo.isSortDesc()) {
					contentData.addDESCColumn(objPropInfo.getFullColumnName());
				}

				if (objPropInfo.isGroupBy()) {
					contentData.addGroupBy(objPropInfo.getFullColumnName());
				}
				if (!TextUtils.isEmpty(WwebserviceVariable)) {
					contentData.getWebServiceParameters().put(
					        objPropInfo.getFullColumnName(),
					        WwebserviceVariable);
				}
				if (objPropInfo.isKey()) {
					contentData.addPrimaryKeys(objPropInfo);
					if (TextUtils.isEmpty(contentData.getMainTable())) {
						contentData.setMainTable(objPropInfo.getTable());
					}
				}
				if (objPropInfo.isFKey()) {
					String primaryTable = null;
					String foriegnTable = null;
					String leftCondition = null;
					String rightCondition = null;
					if (p_om_id == null) {
						primaryTable = objPropInfo.getTable();
						foriegnTable = objPropInfo.getForeignTable();

						if (contentData.isContainTable(foriegnTable)) {
							primaryTable = null;
						}
						leftCondition = objPropInfo.getFullColumnName();
						rightCondition = objPropInfo.getForeignFullColumnName();
					} else if (p_om_id != null) {
						primaryTable = null;
						foriegnTable = objPropInfo.getForeignTable();
						leftCondition = objPropInfo.getFullColumnName();
						rightCondition = objPropInfo.getForeignFullColumnName();
					}
					contentData.addJoin(primaryTable,
					        objPropInfo.getJoinType(), foriegnTable,
					        leftCondition, rightCondition);
					contentData.addForiegnKeys(objPropInfo);
				}

				if (!objPropInfo.getDataRules().isEmpty()) {
					contentData.getDataRules().addAll(
					        objPropInfo.getDataRules());
				}

				contentData.put(objPropInfo.getFullColumnName(), objPropInfo);

				String queryColoum = null;
				if (objPropInfo.getExpression() != null) {
					queryColoum = objPropInfo.getExpression();
				} else {
					queryColoum = objPropInfo.getFullColumnName();
				}
				contentData.getQueriedColumns()
				        .add(queryColoum + " AS "
				                + objPropInfo.getAliasColumnName());
				contentData.getSelectedColumn().add(objPropInfo);

				if (!isIgnoreRefresh) {
					if (!contentData.getRefreshTable().containsKey(
					        objPropInfo.getTable())) {
						contentData.getRefreshTable().put(
						        objPropInfo.getTable(), objPropInfo.getTable());
					}
				}
			}
		}
	}
}
